package com.elbis.access.wg.api.request;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.elbis.access.Constants;
import com.elbis.access.request.Request;
import com.elbis.access.request.RequestEntity;
import com.elbis.access.response.Response;
import com.elbis.access.wg.api.response.WargamingResponseImpl;

public abstract class AbstractWargamingRequestImpl implements Request {

	protected String protocol = null;

	protected String method = null;

	protected String uri = null;

	protected Response response = null;

	protected WOTRequestEntity entity = null;

	private final Logger logger = Logger
			.getLogger(AbstractWargamingRequestImpl.class);

	@Override
	public void execute() {

		if (com.elbis.access.Constants.HTTP_METHOD_GET.equals(method)) {
			executeGetRequest();
		} else if (com.elbis.access.Constants.HTTP_METHOD_POST.equals(method)) {
			executePostRequest();
		} else {
			if (Constants.DEFAULT_METHOD
					.equals(com.elbis.access.Constants.HTTP_METHOD_GET)) {
				executeGetRequest();
			} else if (Constants.DEFAULT_METHOD
					.equals(com.elbis.access.Constants.HTTP_METHOD_POST)) {
				executePostRequest();
			}
		}
	}

	private void executeGetRequest() {

		CloseableHttpClient client = HttpClientBuilder.create().build();
		HttpResponse httpResponse = null;

		HttpGet request = new HttpGet(getFinalURI());
		request.addHeader(Constants.HTTP_CONTENT_TYPE,
				Constants.HTTP_CONTENT_TYPE_PLAIN_TEXT);
		try {
			httpResponse = client.execute(request);
			WargamingResponseImpl responseImpl = new WargamingResponseImpl();

			StatusLine status = httpResponse.getStatusLine();
			responseImpl.setStatus(String.valueOf(status.getStatusCode()));

			if (Constants.HTTP_STATUS_OK == status.getStatusCode()) {
				responseImpl.setHasErrors(false);
			} else {
				responseImpl.setHasErrors(true);
			}
			HttpEntity responseEntity = httpResponse.getEntity();
			if (responseEntity != null) {
				responseImpl.setResponseData(EntityUtils.toString(
						httpResponse.getEntity(), Constants.DEFAULT_ENCODING));
			}
			response = responseImpl;
		} catch (ClientProtocolException e) {
			logger.error("HTTP protocol error at request execution!", e);
		} catch (IOException e) {
			logger.error("I/O error occurend at request execution!", e);
		}
	}

	private void executePostRequest() {

		CloseableHttpClient client = HttpClientBuilder.create().build();
		HttpResponse httpResponse = null;
		HttpPost request = new HttpPost(getFinalURI());
		request.addHeader(Constants.HTTP_CONTENT_TYPE,
				Constants.HTTP_CONTENT_TYPE_PLAIN_TEXT);

		try {
			httpResponse = client.execute(request);
			WargamingResponseImpl responseImpl = new WargamingResponseImpl();

			StatusLine status = httpResponse.getStatusLine();
			responseImpl.setStatus(String.valueOf(status.getStatusCode()));

			if (Constants.HTTP_STATUS_OK == status.getStatusCode()) {
				responseImpl.setHasErrors(false);
			} else {
				responseImpl.setHasErrors(true);
			}
			HttpEntity responseEntity = httpResponse.getEntity();
			if (responseEntity != null) {
				responseImpl.setResponseData(EntityUtils.toString(
						httpResponse.getEntity(), Constants.DEFAULT_ENCODING));
			}
			response = responseImpl;
		} catch (UnsupportedEncodingException e) {
			logger.error("Provided encoding is not supported!", e);
		} catch (ClientProtocolException e) {
			logger.error("HTTP protocol error at request execution!", e);
		} catch (IOException e) {
			logger.error("I/O error occurend at request execution!", e);
		}

	}

	private String getFinalURI() {
		StringBuilder builder = new StringBuilder();
		builder.append(getURIWithProtocol());
		builder.append(getHTTPParameters(entity));
		return builder.toString();
	}

	private String getURIWithProtocol() {
		StringBuilder builder = new StringBuilder();
		builder.append(protocol);
		builder.append(Constants.URL_SEPARATOR);
		builder.append(uri);
		return builder.toString();
	}

	private String getHTTPParameters(RequestEntity entity) {
		if (entity instanceof WOTRequestEntity) {
			WOTRequestEntity wotEntity = (WOTRequestEntity) entity;
			return wotEntity.toHttpRequestParameters();
		} else {
			return null;
		}
	}

	@Override
	public void postProcess() {

	}

	@Override
	public void preProcess() {

	}

	@Override
	public Response getResponse() {
		return response;
	}

	@Override
	public void setProtocol(String protocol) {
		this.protocol = protocol;

	}

	@Override
	public String getProtocol() {
		return protocol;
	}

	@Override
	public void setMethod(String method) {
		this.method = method;
	}

	@Override
	public String getMethod() {
		return method;
	}

	@Override
	public void setUri(String uri) {
		this.uri = uri;
	}

	@Override
	public String getUri() {
		return uri;
	}

}
